package jp.sourceforge.akjrcp.flvtools.basic;

import java.io.File;
import java.io.FilenameFilter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import jp.sourceforge.akjrcp.akj_betas.Akj_betasPlugin;
import jp.sourceforge.akjrcp.akj_betas.FilePlayer;
import jp.sourceforge.akjrcp.akj_betas.Messages;
import jp.sourceforge.akjrcp.util.FileNameUtils;
import jp.sourceforge.akjrcp.util.ProcessMonitor;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.Preferences.IPropertyChangeListener;
import org.eclipse.core.runtime.Preferences.PropertyChangeEvent;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.viewers.DoubleClickEvent;
import org.eclipse.jface.viewers.IDoubleClickListener;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.CCombo;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.DirectoryDialog;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.internal.WorkbenchWindow;
import org.eclipse.ui.part.ViewPart;


public class SimpleView extends ViewPart implements OpenDirectable{
	public static Log log=LogFactory.getLog(SimpleView.class);
	
	public static final String ID = SimpleView.class.getName();

	private FLVDirectoryList directoryList;

	private Button bt1,convertButton;
	
	private CCombo typeCombo;

	private Text pathLabel;
	
	private Action doubleClickAction;
	/**
	 * This is a callback that will allow us to create the viewer and initialize
	 * it.
	 */
	public void openDirectory(){
		DirectoryDialog dialog=new DirectoryDialog(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell());
		String path=dialog.open();
		if(path!=null){
			setDirectory(path);
		}
	}
	private void setDirectory(String path){
		directoryList.setBaseDirectory(new File(path));
		
		directoryList.updateDirectory();
		directoryList.setlectAllUnknown();
		pathLabel.setText(path);
	}
	public static String findBaseDir(){
String baseDir=Akj_betasPlugin.getDefault().getPreferenceStore().getString(FLVToolsPage.Monitor_DIR);
		
		
		
		if(baseDir==null || baseDir.equals("")){
			baseDir=System.getProperty("user.dir");
		}
		
		else if(!new File(baseDir).exists()){
			baseDir=System.getProperty("user.dir");
		}
		return baseDir;
	}
	public void createPartControl(Composite parent) {
		Akj_betasPlugin.getDefault().getPluginPreferences().addPropertyChangeListener( new SettingMonitor());
		
		Composite cp=new Composite(parent,SWT.NULL);
		GridLayout layout=new GridLayout(3,true);
		cp.setLayout(layout);
		
		pathLabel=new Text(cp,SWT.SINGLE|SWT.READ_ONLY);
		GridData data0 = new GridData(GridData.FILL_HORIZONTAL);
		data0.horizontalSpan=3;
		pathLabel.setLayoutData(data0);
		
		directoryList = new FLVDirectoryList(cp, SWT.MULTI | SWT.H_SCROLL
				| SWT.V_SCROLL);
		directoryList.setFilenameFilter(new FLVFilter());
		log.info(directoryList.getContentProvider());
		directoryList.setInput(getViewSite());
		
		String baseDir=findBaseDir();
		pathLabel.setText(baseDir);
		log.debug(baseDir);
		directoryList.setBaseDirectory(new File(baseDir));
		directoryList.updateDirectory();
		directoryList.setlectAllUnknown();
		
		GridData data1 = new GridData(GridData.FILL_BOTH);
		data1.horizontalSpan=3;
		directoryList.getControl().setLayoutData(data1);
		
		bt1=new Button(cp,SWT.NULL);
		bt1.setText(Messages.getString("rename_flv"));
		bt1.addSelectionListener(new RenameAction());
		
		typeCombo=new CCombo(cp,SWT.NULL);
		typeCombo.add("mpg");
		typeCombo.add("avi");
		typeCombo.add("wmv");
		typeCombo.add("mp3");
		typeCombo.add("wav");
		
		typeCombo.add("jpg");
		typeCombo.add("png");
		typeCombo.add("gif");
		typeCombo.select(0);
		
		GridData data4 = new GridData();
		data4.horizontalAlignment=SWT.RIGHT;
		typeCombo.setLayoutData(data4);
		
		
		convertButton=new Button(cp,SWT.NULL);
		convertButton.setText(Messages.getString("convert"));
		
		
		convertButton.addSelectionListener(new FFMpegAction());
		
		GridData data2 = new GridData(GridData.FILL_HORIZONTAL);
		bt1.setLayoutData(data2);
		
		GridData data3 = new GridData(GridData.FILL_HORIZONTAL);
		convertButton.setLayoutData(data3);
		
		
		convertButtonUpdate();
		
		doubleClickAction = new Action() {
			public void run() {
				ISelection selection = directoryList.getSelection();
				
				Object obj=((IStructuredSelection)selection).getFirstElement();
				File file=((File)obj);
				if(file.getName().toLowerCase().endsWith("flv")){
			/*
				Program program=Program.findProgram("flv");
				if(program!=null){
					program.execute(file.getAbsolutePath());
				}else{
					
				}*/
				FilePlayer.play(file);
					
				}
			}
		};
		
		hookDoubleClickAction();
	}
	public void convertButtonUpdate(){
		String ffmpegPath=Akj_betasPlugin.getDefault().getPreferenceStore().getString(FFMpegPage.FFMPEG_PATH);
		if(ffmpegPath.equals("") || !new File(ffmpegPath).exists()){
			convertButton.setEnabled(false);
			directoryList.getTable().setToolTipText(Messages.getString("convert_tooltip"));
		}else{
			convertButton.setEnabled(true);
			directoryList.getTable().setToolTipText("");
		}
	}

	private void hookDoubleClickAction() {
		directoryList.addDoubleClickListener(new IDoubleClickListener() {
			public void doubleClick(DoubleClickEvent event) {
				doubleClickAction.run();
			}
		});
	}
	
	public static boolean isNumberdName(String key){
		String regex =".*\\([0-9]+\\)$";
		Pattern pattern=Pattern.compile(regex);
		Matcher matcher = pattern.matcher(key);
		return matcher.matches();
	}
	public class FLVFilter implements FilenameFilter{

		public boolean accept(File dir, String name) {
			
			
			if(name.indexOf(".")!=-1){
				if(!name.toLowerCase().endsWith(".flv")){
					return false;
				}
			}
			File tmp=new File(dir,name);
			if(tmp.isHidden()){//i don't know
				return false;
			}
			
			if(tmp.isDirectory()){
				return false;
			}
			if(tmp.length()<1024*10){ //i limit 10k
				return false;
			}
			if(name.equals("NTLDR")){ //
				return false;
			}
			
			if(name.equals("~")){//i don't know
				return false;
			}
			
			boolean result=FLVUtil.isFLVFileFormat(tmp);
			log.info(result+" "+tmp.getName());
			return result;
		}
		
	}
	
	public class SettingMonitor implements IPropertyChangeListener{

		public void propertyChange(PropertyChangeEvent event) {
			log.info(event.getProperty());
			if(event.getProperty().equals(FLVToolsPage.Monitor_DIR)){
				
				String baseDir=Akj_betasPlugin.getDefault().getPreferenceStore().getString(FLVToolsPage.Monitor_DIR);
				
				setDirectory(baseDir);
			}
			else if(event.getProperty().equals(FFMpegPage.FFMPEG_PATH)){
				
				convertButtonUpdate();
			}
		}
		
	}

	
	
	public class RenameAction implements SelectionListener{

		public void widgetSelected(SelectionEvent e) {
			
			File file[]=directoryList.getSelectionFiles();
			for (int i = 0; i < file.length; i++) {
				if(isValidFLV(file[i])){
					
					boolean result=FileNameUtils.changeExtension(file[i],"flv");
					log.warn(result+","+file[i].getName());
				}
			}
			directoryList.updateDirectory();
		}

		public void widgetDefaultSelected(SelectionEvent e) {
			
		}
		
		public boolean isValidFLV(File file){
			if(file.isFile() && file.getName().indexOf(".")==-1){
				return true;
			}
			return false;
		}
	}
	
	
	public File convertingFile[];
	IProgressMonitor convertMonitor;
	
	private String extension;

	public int CONVERT_TASK=20;
	public class FFMpegAction  implements SelectionListener{

		public File[] filterConvertingFile(){
			ArrayList array=new ArrayList();
			File list[]=directoryList.getSelectionFiles();
			for (int i = 0; i < list.length; i++) {
				if(list[i].getName().toLowerCase().endsWith(".flv")){
					array.add(list[i]);
				}
			}
			return (File[]) array.toArray(new File[0]);
		}
		public void widgetSelected(SelectionEvent e) {
			
			// TODO Auto-generated method stub
			convertButton.setEnabled(false);
			
			WorkbenchWindow workbenchWindow = (WorkbenchWindow)PlatformUI.getWorkbench().getActiveWorkbenchWindow();
	        
		       // lineManager.insertBefore(lineManager.get,status1);
		        //lineManager.setMessage("tmp.ogg - [16bit 44.1khz Stereo] - 10:24:1024");
		        
		        
		        
		        //workbenchWindow.getStatusLineManager().setMessage("open");
		        
			convertMonitor=workbenchWindow.getStatusLineManager().getProgressMonitor();
			
		        convertingFile=filterConvertingFile();
		        convertMonitor.beginTask(Messages.getString("converting"),convertingFile.length);
		        
		        extension=typeCombo.getText();
			new FFMpegExecuter().start();
			
		}

		public void widgetDefaultSelected(SelectionEvent e) {
			
		}
	}
	public class FFMpegExecuter extends Thread{
		public void debugArray(String[] array){
			String v="";
			for (int i = 0; i < array.length; i++) {
				v+="\""+array[i]+"\""+" ";
			}
			Akj_betasPlugin.getDefault().getProcessPrinter().printOutput(v+"\n");
		}
		
		public boolean isImageExport(String extension){
			return extension.equals("png") || extension.equals("jpg") || extension.equals("gif");
		}
		
		public void run(){
			for(int i=0;i<convertingFile.length;i++){
				PlatformUI.getWorkbench().getDisplay().syncExec(new ConvertMonitorStartSubTask(convertingFile[i].getName()));
			ProcessMonitor monitor=null;
			Runtime runtime=Runtime.getRuntime();
			ArrayList param=new ArrayList();
			IPreferenceStore store=Akj_betasPlugin.getDefault().getPreferenceStore();
			String ffmpegPath=store.getString(FFMpegPage.FFMPEG_PATH);
			param.add(ffmpegPath);
			param.add("-i");
			
			param.add(convertingFile[i].getAbsolutePath());
			
			if(isImageExport(extension)){
				param.add("-f");
				param.add("image2");
				param.add("-ss");
				param.add(store.getString(FFMpegPage.IMAGE_TIME));
				param.add("-vframes");
				param.add("1");
			}else{
			param.add("-b");
			param.add(""+store.getInt(FFMpegPage.VIDEO_BITRATE));
			param.add("-ab");
			param.add(""+store.getInt(FFMpegPage.AUDIO_BITRATE));
			param.add("-ar");
			param.add(""+store.getInt(FFMpegPage.EXPORT_WAVE_SAMPLERATE));
			param.add("-ac");
			param.add(""+store.getInt(FFMpegPage.EXPORT_WAVE_CHANNEL));
			
			param.add("-r");
			param.add(store.getString(FFMpegPage.VIDEO_FPS));
			
			String optionString=store.getString(FFMpegPage.FFMPEG_OPTION);
			
			if(extension.equals("avi")){
				param.add("-vcodec");
				param.add(store.getString(FFMpegPage.VIDEO_CODEC));
				param.add("-acodec");
				param.add("mp3");
			}else if(extension.equals("wmv")){
				param.add("-vcodec");
				param.add("wmv2");
				param.add("-acodec");
				param.add("mp3");
			}
			
			//Special trick CBR Encoding
			if(store.getString(FFMpegPage.MPEG_TYPE).equals(FFMpegPage.MPEG_TYPE_CBR)){
				param.add("-maxrate");
				param.add(""+store.getInt(FFMpegPage.VIDEO_BITRATE));
				param.add("-minrate");
				param.add(""+store.getInt(FFMpegPage.VIDEO_BITRATE));
				param.add("-bufsize");
				param.add("128");
			}
			
			String[] options=optionString.split(" ");//buggy
			for (int j = 0; j < options.length; j++) {
				param.add(options[j]);	
			}
			
			
			}
			
			param.add(FileNameUtils.getChangedExtensionName(convertingFile[i],extension));
			try {
				String arg[]=(String[])param.toArray(new String[0]);
				debugArray(arg);
				Process p=runtime.exec(arg);
				
				monitor=new ProcessMonitor(p,Akj_betasPlugin.getDefault().getProcessPrinter());
				monitor.startMonitor();
				
				
				try {
					p.waitFor();
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			
			monitor.stop();
			PlatformUI.getWorkbench().getDisplay().syncExec(new ConvertMonitorProcess());
			}
			
			PlatformUI.getWorkbench().getDisplay().syncExec(new ConvertMonitorDone());
			
			PlatformUI.getWorkbench().getDisplay().syncExec(new FinishAction());
			//finish
			PlatformUI.getWorkbench().getDisplay().syncExec(new EnableControl(convertButton));
			
		}
	}
	
	public class ConvertMonitorStartSubTask extends Thread{
		String name;
		public ConvertMonitorStartSubTask(String name){
			this.name=name;
		}
		public void run(){
			log.warn(name);
			convertMonitor.subTask(name);
		}
	}
	
	public class ConvertMonitorProcess extends Thread{
		
		public void run(){
			
			convertMonitor.worked(1);
		}
	}
	
	public class FinishAction extends Thread{
		public void run(){
			directoryList.updateDirectory();
		}
	}
	

	
	public class ConvertMonitorDone extends Thread{
		public void run(){
			convertMonitor.done();
		}
	}

	public class EnableControl extends Thread{
		Control composite;
		public EnableControl(Control cp){
			composite=cp;
		}
		public void run(){
			composite.setEnabled(true);
		}
	}
	/**
	 * Passing the focus request to the viewer's control.
	 */
	public void setFocus() {
		directoryList.getControl().setFocus();
	}
	
	
		
}